Patching Petite.
================

Tutorial on patching a packed file  :-)nothing is impossible(-:

Written by R!SC - risc_1@hotmail.com

Knowledge is Power!


Introduction
============

Hi,
 My task today is to teach all you crackers how to patch a packed file. How many times have you
come across a program that you want to crack, only to find out it has been packed with 'Petite'?
since there are no Unpackers for petite(well, none that leave you with a file that runs) we have
to use petites own unpacking code, use the jump to the start of the original code to jump to our
patch, patch the code in memory, then return execution to the original program. This was my 
theory, and after a few hours of messing around with a packed file, i managed to do it.

tHE IDEA OF THIS TUTORIAL IS NOT TO TEACH CRACKING, BUT PATCHING A FILE PACKED WITH pETITE.

things you will need!

Petite 1.3a (Target demonstration file..petite.exe  46,600 bytes)
available from  http://www.icl.ndirect.co.uk/petite/

Soft Ice for windoze
A Hex Editor of your choice
some asm programming knowledge
maybe WDasm32
!!!PEN AND PAPER!!! (oLD sKOOL :-)

Being a cracker, you will already have all of these things, and probably know how to patch packed
files, but i have never seen a tutorial on it, and I'm sure some people will appreciate this one.

You already know how to tell if a files packed with petite don't you, it has a .petite object,
it normally say 'Compressed by Petite, Copyright(c)1998 Ian Luck' in the first 255 bytes of the
exe.


Lets begin...
=============

Before we do begin, get your pen & paper ready and lets write down some variables. We need two 
file offsets, at least three memory addresses copying down, and two patchdata arrays?
do it like this (this is VERY important if you want to follow along)

OFFSET#1   ; FILE OFFSET-WORD
OFFSET#2   ; FILE OFFSET-WORD
ADDR#1     ; MEMORY ADDRESS-LONG
ADDR#2     ; MEMORY ADDRESS-LONG
ADDR#3...  ;  "               "
PATCH#1    ; 5 BYTES (OUR CALL TO OUR PATCH)
PATCH#2    ; PHAT BLOCK OF DATA

Petite unpacks the program, then calls the tamper check routine(which it also unpacked) if this
passes, the program runs. To find the call to the tamper check routine, load petite.exe into a
hexeditor and search for '5e5bc9c3e8', get the offset of the 'e8'(the first byte of the call
command) and write down OFFSET#1 . Your offset should be 17eb. Scroll down from the current
offset past the imports until you get to a block of zeros. 1cf0 is a nice place. write down
OFFSET#2

00001CD0  65 42 6F 78 41 00 4B 45 52 4E 45 4C 33 32 2E 64 eBoxA.KERNEL32.d
00001CE0  6C 6C 00 75 73 65 72 33 32 2E 64 6C 6C 00 00 00 ll.user32.dll...  <-- eND oF iMPORTS
00001CF0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................  <-- wHERE oUR cODE cAN gO


At OFFSET#1 change the 'e8' to a 'cc' (int 03).
At OFFSET#2 enter 'sometext', save the file.
Enter softice, type in 'bpint 3', exit softice, run petite.exe.
We are back in softice now, type in 'd eip'
the 'cc' should be the first byte in the data window, change this back to a 'e8'
write down ADDR#1 the address the call is calling 'call 0040DDB0'
type in 't 40' (traces 40 commands automatically)
you reach a bit of code like this

40de2a  xor ebx, [esi]
40de2c  rol ebx, cl
40de2e  add esi, 04
40de31  dec ecx
40de32  jnz 40de2a
40de34  cmp [eax + 04], ebx
40de37  jz  40de41  <-- this jump means its not been tampered with

Write down the address of the jz 40de41 in ADDR#2 (40de37)

Type in 's 0 l ffffffff "sometext"'
Write down the address it gives you in ADDR#3 (45aaf0)

If you've already cracked the exe you want to patch, search for the bytes near your crack, and 
write down ADDR#4....ADDR#x

I chose to change the text in petite.exe that says " $HAREWARE - see REGISTER.TXT for details"
to read "                                           " (heh)

Type in 's 0 l ffffffff "$HAREWARE"'
write down ADDR#4 (40f83b)

Hit F5 to run the program and get back to windoze...

We have the file offset for the call to the check, we have the entry address for the check, we
have the address of the jump that it takes if its not been tampered with, we have the memory
address where our patch is going to go. We have the memory addresses of our crack(s).Now we
need to write our patch in a patch thingy.


Get Cracking.
=============

Right then, in soft-ice, i presume we have a data window (WD), (code on), register window (wr),
big display (lines 50 or 60)...

get your piece of paper ready with all addresses written on it ;)
----------------------------------------------------------------------

OFFSET#1  = 17eb    (call to tamper check)
OFFSET#2  = 1cf0    (space after imports to put our patch)
ADDR#1    = 40ddb0  (call to tamper check)
ADDR#2    = 40de37  (address of tamper check conditional jump)
ADDR#3    = 45aaf0  (address in memory where our patch will be loaded)
ADDR#4    = 40f83b  (unpacked text what we want to patch)
PATCH#1   = WAIT
PATCH#2   = 4 IT
----------------------------------------------------------------------

Run the program again. Softice breaks on the int 03
use softice's built in assembler to alter the call to the tamper check.

type in 'a eip'
type in 'call 45aaf0' (ADDR#3 -- 'sometext')
press <esc> to stop assembly
type in 'd eip'
Write down the first 5 bytes displayed in the data window 'e800050000' in PATCH#1
Hit F8 to execute the call command. eip should = ADDR#3
type in 'a eip'
>mov byte ptr [ADDR#2], eb    ; kill tamper check
>mov word ptr [ADDR#4], 000a  ; back to front bytes again, lf,0 "$HARE..." is a null terminated string
>mov xxxx ptr [ADDR#x], your crackz ; 
>jmp ADDR#1                   ; our patch has finished, return control to petite...
press <esc>
type in 'd eip'
copy all the bytes to your instructions >> PATCH#2

PATCH#1 = e8,00,05,00,00              ; call 45aaf0
PATCH#2 = c6,05,37,de,40,00,eb        ; mov byte ptr [40de37], eb
          66,c7,05,3b,f8,40,00,0a,00  ; mov word ptr [40f83b], 000a
          e9,ab,32,fb,ff              ; jmp 40ddb0



execute the code step by step, checking the addresses its patching, to make sure it does it 
right. Now all you need to do is get all your data into a patching program, to patch petite.exe
with your inline patch.... e.g.


;---------------------start of risc_pet.asm---------------------
; to build risc_pet.com
;
; tasm risc_pet
; tlink /t risc_pet


.MODEL TINY
.CODE
.286
ORG 100h

start:  jmp main

;_______________________________________________________________

intro   db 0dh,0ah," Hi, guess who cracked Petite?",0dh,0ah
        db "  It was cracked by -R!SC- ",0dh,0ah,0dh,0ah,"$"

done    db " Groovy! Patch Successful",0Dh,0Ah,"$"

error   db "  cant find file ? ",0Dh,0Ah,"$"
error2  db "  file wrong size, should be 46,600 bytes ",0Dh,0Ah,"$"

filename  db "petite.exe",0

PATCH1 db 0e8h,00,05,00,00                 ; call 45aaf0

PATCH2 db 0c6h,005h,037h,0deh,040h,000h,0ebh     ; mov byte ptr [40de37], eb
       db 066h,0c7h,005h,03bh,0f8h,040h,0,0ah,0  ; mov word ptr [40f83b], 000a
       db 0e9h,0abh,032h,0fbh,0ffh               ; jmp 40ddb0

; 21 bytes of code to apply to the file + another 5 for the call to our code...
;_______________________________________________________________

main:
        mov     ah, 9           ; print title
        lea     dx, intro       ; dx with offset of text
        int     21h

        mov     ax, 3D02h       ; Open File
        lea     dx, filename
        int     21h
        jnb     Ok          ; jump if everything ok

        mov     ah, 9       ; error with file
        lea     dx, error
        int     21h
        mov     ax, 4C01h   ; Exit with error
        int     21h
;_______________________________________________________________
Ok:

        mov     bx, ax
        mov     ax, 4202h   ; seek eof
        xor     cx, cx
        xor     dx, dx
        int     21h
        cmp     ax, 0b608h  ; 46,600 
        jne     badsize
        cmp     dx, 0
        jne     badsize

sizepassed:

        mov     ax, 4200h   ; file seek
        mov     cx, 0       ; hi order word of offset
        mov     dx, 017ebh  ; lo order word of offset  OFFSET#1
        int     21h

        mov     ax, 4000h   ; Write to file
        mov     cx, 5       ; number of bytes to write
        lea     dx, PATCH1
        int     21h

        mov     ax, 4200h   ; file seek
        mov     cx, 0            
        mov     dx, 01cf0h  ; OFFSET#2         
        int     21h

        mov     ax, 4000h      
        mov     cx, 21          
        lea     dx, PATCH2
        int     21h

        mov     ax, 3E00h   ; Close file
        int     21h

        mov     ah, 9       ; Show msg
        lea     dx, done
        int     21h

        mov     ax, 4C00h   ; All Done And Exit 
        int     21h


badsize:
        mov     ah, 9       ; print to screen
        lea     dx, error2  ; message
        int     21h
        mov     ax, 4C01h   ; Exit with error
        int     21h


  end    start


;-----------------------end of risc_pet.asm---------------------


Taking a look at this Hex Dump of petite.exe, you will see that we have plenty of space between
the end of the imports and the start of the packed data to write our patch (about 274 bytes!)

00001CD0  65 42 6F 78 41 00 4B 45 52 4E 45 4C 33 32 2E 64 eBoxA.KERNEL32.d
00001CE0  6C 6C 00 75 73 65 72 33 32 2E 64 6C 6C 00 00 00 ll.user32.dll...  <-- eND oF iMPORTS
00001CF0  C6 05 37 DE 40 00 EB 66 C7 05 3B F8 40 00 0A 00 ..7.@..f..;.@...  <-- mY pATCH cODE
00001D00  E9 AB 32 FB FF 00 00 00 00 00 00 00 00 00 00 00 ..2.............  <-- mY pATCH cODE
00001D10  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................  }
00001D20  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................   }
00001D30  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................   }
00001D40  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................   }
00001D50  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................  }
00001D60  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................  }
00001D70  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................   }
00001D80  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................    } pLENTY oF sPACE fOR
00001D90  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................   }   bIG pATCH iF nEEDED
00001DA0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................  }
00001DB0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................  }  
00001DC0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................   }
00001DD0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................   }
00001DE0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................   }
00001DF0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................  }
00001E00  CA BD 0D 7C 14 D5 B9 38 3C BB 3B 49 86 B0 61 36 ...|...8<.;I..a6  <-- sTART oF pACKED dATA
00001E10  B0 81 05 22 46 5D 6B 74 41 83 1B 94 B0 A0 09 66 ..."F]ktA......f

in every file ive seen compressed with petite, there's always a bit of space between the imports
and before the packed data where you can write your patch.

comments, suggestions, questions welcome, write in the subject 'petite patching'

  risc_1@hotmail.com

R!SC -- January 1999 

(I will survive without you.
 Don't tell me that you wanna leave.
 
 If you wanna leave, I wont beg you to stay,
 and if you gotta go darling, maybe its better that way.
 
 I'm gonna be strong, i'm gonna be fine,
 don't worry about this heart of mine.)

Big hug to SaM, LoVE u, MiSSiNG u, fEW mORE dAYZ oF bORDEM, tHEN yA bACK !)



How to WDasm Petite.
====================
So you want to see the decompression code? Load petite into W32Dasm, i have included a cut down
version of the listing here. What i do is change the .text object to match the data of the
.petite object. RVA is the Relative Virtual Address address of where to load the object (+
imagebase), Offset is the actual offset in the file, Size ;) and Flag bits for the object.

The object flag bits have the following definitions:

  o  000000020h __Code object.   
  o  000000040h __Initialized data object.   
  o  000000080h __Uninitialized data object.   
  o  040000000h __Object must not be cached.   
  o  080000000h __Object is not pageable.   
  o  100000000h __Object is shared.   
  o  200000000h __Executable object.
  o  400000000h __Readable object.
  o  800000000h __Writeable object.


Disassembly of File: PETITE.EXE
Code Offset = 00001E00, Code Size = 00009808
Data Offset = 00001E00, Data Size = 00009808

Number of Objects = 0002 (dec), Imagebase = 00400000h

   Object01: .text    RVA: 00001000 Offset: 00001E00 Size: 00009808 Flags: E0000060
   Object02: .petite  RVA: 00059000 Offset: 00000200 Size: 00001C00 Flags: E2000060

+++++++++++++++++++ ASSEMBLY CODE LISTING ++++++++++++++++++
//********************** Start of Code in Object .text **************
Program Entry Point = 004590CE (PETITE.EXE File Offset:000002CE)


We have all the data here that we need, jot down the entry point (2CE), the RVA(00059000), the
size (1C00), forget about the flags. Hex Edit petite.exe, offset 170h, as you will notice,
everything is back to front! (can use the PE Editor in ProcDump if u like, its a bit easier)

00000170 00 00 00 00 00 00 00 00 2E 74 65 78 74 00 00 00  .........text...
00000180 00 80 05 00 00 10 00 00 08 98 00 00 00 1E 00 00  ................
                     00 00 10 00 00 00 98 08 00 00 1E 00
                     ^^^^RVA^^^^ ^^^^size^^^ ^^^offset^^

change the RVA, Size and Offset like so...

00000170 00 00 00 00 00 00 00 00 2E 74 65 78 74 00 00 00  .........text...
00000180 00 80 05 00 00 90 05 00 00 1C 00 00 CE 02 00 00  ................
                     00 05 90 00 00 00 1C 00 00 00 02 CE
                     ^^^^RVA^^^^ ^^^^size^^^ ^^^offset^^
 
Load it back into WDasm and your rewarded with a disassembly listing of the decompression code!


+++++++++++++++++++ ASSEMBLY CODE LISTING ++++++++++++++++++
//********************** Start of Code in Object .text **************
Program Entry Point = 004590CE (Petite.exe File Offset:000002CE)

snip 459000-4590CD

//******************** Program Entry Point ********
:004590CE B800904500              mov eax, 00459000
:004590D3 669C                    pushf
:004590D5 60                      pushad
:004590D6 50                      push eax
:004590D7 8D8800E00000            lea ecx, dword ptr [eax+0000E000]
:004590DD 8D90F8150000            lea edx, dword ptr [eax+000015F8]
:004590E3 8BDC                    mov ebx, esp
:004590E5 8BE1                    mov esp, ecx
:004590E7 6800004000              push 00400000
:004590EC 53                      push ebx
:004590ED 50                      push eax
:004590EE 80042408                add byte ptr [esp], 08
:004590F2 50                      push eax
:004590F3 80042442                add byte ptr [esp], 42
:004590F7 50                      push eax
:004590F8 80042461                add byte ptr [esp], 61
:004590FC 50                      push eax
:004590FD 8004249D                add byte ptr [esp], 9D
:00459101 50                      push eax
:00459102 800424BB                add byte ptr [esp], BB

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00459130(U), :00459166(U)
|
:00459106 833A00                  cmp dword ptr [edx], 00000000
:00459109 0F84DC140000            je 0045A5EB       <--- this is the bit were intrested in
                                                      -- signifies unpacking has finished, and
                                                       - calls the tamper check (that it unpacked)
 
I dont understand the code, but i know this je 0045A51D jumps to a call that calls a very low
address, with a jump right afterwards (which never gets taken...)
 
:0045A5E7 5E                      pop esi    <-- when you come accross other files packed with petite
:0045A5E8 5B                      pop ebx      - search the exe for these bytes
:0045A5E9 C9                      leave        - 5e,5b,c9,c3,e8
:0045A5EA C3                      ret          - the e8 is the first byte to the call to the tamper
                                               - check, replace it with 'cc' (int 3) and bpint 3 in softice

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00459109(C)
|
:0045A5EB E8C037FBFF              call 0040DDB0   <-- hi baby.
:0045A5F0 E92DEAFAFF              jmp 00409022
 
risc@notme.com
risc_1@hotmail.com

love me, hate me, u dont no me...
